/// Project entry point
/// ----------------------------------------------------
/// @Project :   xinhou-rocket-admin
/// @File    :   main.rs
/// @Contact :   sp_hrz@qq.com
///
/// @Modify Time      @Author    @Version    @Description
/// ------------      -------    --------    -----------
/// 2024/07/04 17:43   shenpeng   1.0         None
#[macro_use]
extern crate rocket;

use std::any::Any;
use std::env;

use dotenv::dotenv;
use rocket::{Build, Config, Rocket};
use rocket_okapi::swagger_ui::{make_swagger_ui, SwaggerUIConfig};

use crate::business::auto_services::apps_auto_service;
use crate::extends::core::cached::redis_manager::RedisManager;
use crate::extends::core::common::default_controller::health;
use crate::extends::core::config::app_context::AppContext;
use crate::extends::core::config::app_ctx_handler::AppCtxHandler;
use crate::extends::core::db::db_manager::DatabaseManager;
use crate::extends::core::errors::error_handler::{internal_error, not_found};
use crate::extends::core::initialize::banner as Banner;
use crate::extends::core::logger::log_handler::LogHandler;

mod apps;
mod business;
mod extends;

// Include the generated routes file from src/apps directory
include!("apps/auto_routes.rs");

/// Rocket launch function
#[launch]
async fn rocket() -> Rocket<Build> {
    // Load environment variables from .env file
    dotenv().ok();
    // Read application configuration from YAML file
    let app_ctx_config: AppContext = AppCtxHandler::load_config();

    // Initialize logger
    LogHandler::new(&app_ctx_config.framework.logging.path, log::LevelFilter::Info).initialize().expect("Failed to initialize logger");


    // Initialize banner with application configuration
    let base_path = env::current_dir().unwrap();
    Banner::init_banner(
        &format!("{}/banner.txt", base_path.display()),
        &app_ctx_config.clone(),
    );

    // Initialize database connection pool
    let db_pool = DatabaseManager::init_mysql_pool(&app_ctx_config.framework.datasource.clone())
        .await
        .expect("Failed to create database pool.");

    // Initialize redis connection pool
    let redis_pool = RedisManager::init_redis_pool(&app_ctx_config.framework.redis.clone())
        .await
        .expect("Failed to create redis pool.");

    // Initialize application context beans
    let app_ctx_beans = apps_auto_service(db_pool.clone());

    // Create and configure Rocket instance
    rocket::custom(Config {
        address: app_ctx_config.application.server.host.parse().expect("Invalid address"),
        port: app_ctx_config.application.server.port,
        ..Config::debug_default()
    })
        .manage(db_pool)
        .manage(redis_pool)
        .manage(app_ctx_config)
        .manage(app_ctx_beans)
        .mount("/", routes![health])
        .mount("/",apps_auto_routes())
        .mount(
            "/swagger-ui/",
            make_swagger_ui(&SwaggerUIConfig {
                url: "../openapi.json".to_owned(),
                ..Default::default()
            }),
        )
        .register("/", catchers![not_found, internal_error])
}
